﻿#include "stdafx.h"
#include "NatRacingApp.h"
#include "PhysXObj.h"
#include "PhysicsManager.h"
#include "Car.h"
#include "Camera.h"
#include "EffectManager.h"
#include "SoundTools.h"
// #include "..\3rdLib\ogreosm\OgreOSMScene.h"
// #include "..\3rdLib\OGREMax\OgreMaxScene.hpp"


#include "AngelScriptBinder.h"
#include "GraphicScriptBinder.h"
#include "ShowVideo.h"
#include "GameCore.h"
#include "UISystem.h"

#include "DebugAssert.h"

CEGUI::MouseButton convertOISMouseButtonToCegui(int buttonID)
{
	switch (buttonID)
	{
	case 0: return CEGUI::LeftButton;
	case 1: return CEGUI::RightButton;
	case 2:	return CEGUI::MiddleButton;
	case 3: return CEGUI::X1Button;
	default: return CEGUI::LeftButton;
	}
}

NatRacingFrameListener::NatRacingFrameListener( RenderWindow* win, Camera* cam , CEGUI::Renderer* renderer) 
	: OGREFrameListener(win, cam, true, true, true),
	mGUIRenderer(renderer),
	mShutdownRequested(false)
{
	mMouse->setEventCallback(this);
	mKeyboard->setEventCallback(this);
	SAVE_LOG("OGRE图形引擎初始化成功");
}

void NatRacingFrameListener::requestShutdown()
{
     mShutdownRequested = true;
}

bool NatRacingFrameListener::frameEnded(const FrameEvent& evt)
{
	if (mShutdownRequested)
		return false;
	else
		return OGREFrameListener::frameEnded(evt);
}

// MouseListener
bool NatRacingFrameListener::mouseMoved(const OIS::MouseEvent &arg)
{
	CEGUI::System::getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);

	return true;
}

bool NatRacingFrameListener::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(id));

	return true;
}

bool NatRacingFrameListener::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(id));

	return true;
}

// KeyListener
bool NatRacingFrameListener::keyPressed( const OIS::KeyEvent &arg )
{
	if (arg.key == OIS::KC_SYSRQ)
	{
		std::ostringstream ss;
		string time;
		Clock::GetSysTime(time);
		ss << time << ".png";
		mWindow->writeContentsToFile(ss.str());
	}
#ifdef NR_DEBUG
	else if(arg.key == OIS::KC_R)
	{
		mCamera->setPolygonMode(PM_SOLID);
	}
	else if(arg.key == OIS::KC_T)
	{
		mCamera->setPolygonMode(PM_WIREFRAME);	
	}
	else if( arg.key == OIS::KC_ESCAPE )
	{
		mShutdownRequested = true;
		UiSystem::Instance()->Release();
		return true;
	}
#endif
		
	CEGUI::System::getSingleton().injectKeyDown( arg.key );
	CEGUI::System::getSingleton().injectChar( arg.text );
	return true;
}

bool NatRacingFrameListener::keyReleased( const OIS::KeyEvent &arg )
{
	CEGUI::System::getSingleton().injectKeyUp( arg.key );
	return true;
}

//////////////////////////////////////////////////////////////////////////


void NatRacingApp::chooseSceneManager( void )
{
	// Get the SceneManager, in this case a generic one

	mSceneMgr = mRoot->createSceneManager("TerrainSceneManager");
	assert(mSceneMgr);
	OgreProperty::Instance()->sceneManager = mSceneMgr;
}

void NatRacingApp::createCamera( void )
{
	// 创建摄像机
	mCamera = mSceneMgr->createCamera("PlayerCam");
	// Position it at 500 in Z direction
	mCamera->setPosition(0, 20, 80);
	mCamera->lookAt(0, 20, 0);
	mCamera->setNearClipDistance( 1 );
	//mCamera->setFarClipDistance( 1000 );
	//传递摄像机给自己用
	CameraCenter::Instance()->Initial(mCamera);
}

void NatRacingApp::createFrameListener( void )
{
	mFrameListener= new NatRacingFrameListener(mWindow, mCamera, UiSystem::Instance()->GetUIRender());
	mRoot->addFrameListener(mFrameListener);
	SAVE_LOG("帧监听创建完毕");
}


void NatRacingApp::createScene( void )
{

//	mSceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_TEXTURE_MODULATIVE);
//	mSceneMgr->setShadowFarDistance(1000);

	//mSceneMgr->setAmbientLight( ColourValue( 1, 1, 1 ) );//为整个场景设置环境光
//	Ogre::MovableObject::setDefaultVisibilityFlags(0x00000001);

	// Set ambient light
//	mSceneMgr->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.2));

	//光照
//	Ogre::Light* l = mSceneMgr->createLight("Light2");
//	Ogre::Vector3 dir(-1,-1,0);
///	dir.normalise();
//	l->setType(Ogre::Light::LT_DIRECTIONAL);
//	l->setDirection(dir);
//	l->setDiffuseColour(1, 1, 0.8);
//	l->setSpecularColour(1, 1, 1);

	OgreProperty::Instance()->root = mRoot;

	// Create System Object to be used by OgitorsRoot
	m_System = new CWinSystem(mWindow);
	// Create Ogitors FrameWork Root
	ogRoot = new Ogitors::OgitorsRoot();
	// Notify the Root about our Render Window

	assert(ogRoot);
	OgreProperty::Instance()->ogRoot = ogRoot;

	ogRoot->SetRenderWindow(mWindow);

	// Hide Light Holder Objects
	ogRoot->SetLightVisiblity(false);
	// Hide Camera Holder Objects
	ogRoot->SetCameraVisiblity(false);

	SceneManager *mSecondSceneMgr = mRoot->createSceneManager(ST_GENERIC, "SecondSceneMgr");
	OgreProperty::Instance()->sceneManager = mSecondSceneMgr;
	assert(mSecondSceneMgr);

	// 创建摄像机
	mCamera = mSecondSceneMgr->createCamera("PlayerCam");

	mViewport = mWindow->addViewport(mCamera, 0, 0, 0, 1, 1);
	mViewport->setBackgroundColour(ColourValue(0,0,0));
	mCamera->setAspectRatio(Real(mViewport->getActualWidth()) / Real(mViewport->getActualHeight()));

	/// 等待logo播放完毕
	ShowVideo::Instance()->WaitForOver();

	//// 执行脚本的创建场景函数
	AngelScriptBinder::Instance()->RunScriptFunction(NULL,"void CreateScene()",0);

	/// 释放dshow接口
	ShowVideo::Instance()->CleanUp();

	// 雾境效果
	// 	ColourValue fadeColour(0.93, 0.86, 0.76);
	// 	mSceneMgr->setFog( FOG_LINEAR, fadeColour, 0.001, 500, 1000);
	// 	mWindow->getViewport(0)->setBackgroundColour(fadeColour);


	// 动态穹顶
	//MaterialPtr skyMat = MaterialManager::getSingleton().create("SkyMat",
	//	ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
	//skyMat->setLightingEnabled(false);
	//TextureUnitState* t = skyMat->getTechnique(0)->getPass(0)->createTextureUnitState("clouds.jpg");
	//t->setScrollAnimation(0.05, 0);
	//mSceneMgr->setSkyDome(true, "SkyMat", -5, 2);

	//////////////////////////////////////////////////////////////////////////
	//// 无穷远的平面？
	if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_INFINITE_FAR_PLANE))
	{
		mCamera->setFarClipDistance(0);//设置远距离裁剪
	}

	// ofusion场景测试

 	//SceneNode * mnode=mSceneMgr->getRootSceneNode()->createChildSceneNode("PathScene_01");
	//OSMScene* mmoScene=new OSMScene(mSceneMgr,mWindow);
	//OSMSceneCallbacks oe_Callback;
	//mmoScene->initialise("circlerace.osm", &oe_Callback);
	//mmoScene->createScene(mnode);

	//OgreMax::OgreMaxScene* m_maxScene =  new OgreMax::OgreMaxScene();
	//m_maxScene->Load("pal.scene",mWindow,OgreMax::OgreMaxScene::NO_OPTIONS,mSceneMgr,mnode);

}

void NatRacing::NatRacingApp::destroyScene(void)
{
	ogRoot->TerminateScene();
	delete ogRoot;
	delete m_System;
}


bool NatRacing::NatRacingApp::configure( void )
{
 
 //#ifdef _DEBUG
 //	mRoot->loadPlugin("RenderSystem_Direct3D9_d");
 //	//mRoot->loadPlugin("RenderSystem_GL_d");
 //#else
 //	mRoot->loadPlugin("RenderSystem_Direct3D9");
 //	//mRoot->loadPlugin("RenderSystem_GL");
 //#endif
 //

  	String rName("Direct3D9 Rendering Subsystem");
  
  	RenderSystemList rList = mRoot->getAvailableRenderers();
  	RenderSystemList::iterator it = rList.begin();
  	RenderSystem *rSys = 0;
  
  	while(it != rList.end())
  	{
  		rSys = * (it++);
  		if(rSys->getName() == rName)
  		{    
  			//设置渲染器，并结束循环
  			mRoot->setRenderSystem(rSys);
  			break;
  		}
  	}
  
  	//如果没有找到一个可用的渲染器，就在这里结束程序。
  	if(mRoot->getRenderSystem() == NULL)
  	{
  		delete mRoot;
  		return -1;
  	}
 
  
  	OgreProperty::Instance()->configDesc.SetConfig(rSys);
  	
  	mWindow = mRoot->initialise(true);

	SAVE_LOG("渲染窗口启动");

	assert(mWindow);
	OgreProperty::Instance()->window = mWindow;

	ShowVideo::Instance()->Initial();
	ShowVideo::Instance()->PlayVideo("..\\..\\media\\video\\logo.avi");

	NatRacing::GameCore::Instance()->Initial();

	return true;
	
}

void NatRacingApp::loadResources()
{
	// Initialise the rest of the resource groups, parse scripts etc
	ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
	AngelScriptBinder::Instance()->RunScriptFunction(NULL,"void Compiler()",0);
}
